self.Module = {
  onRuntimeInitialized: function () {
    console.log("load");

    onLoad();
  },
};

// import * as Module from "./libffmpeg.js";

// 导入脚本
self.importScripts("libffmpeg.js");

interface Req {
  t: number;
  d?: ArrayBuffer;
  u?: string;
  ms?: string;
  s?: number;
  c?: number;
  i?: number;
}

// 精确seek标志
let accurateSeek = true;
// WebAssembly是否加载完成标志
let wasmLoaded = false;
// 临时请求队列
let tmpReqQue: Array<ArrayBuffer> = [];
// 缓存缓冲区
let cacheBuffer: any = null;
// 解码定时器
let decodeTimer: number | null = null;
// 视频回调函数
let videoCallback: any = null;
// 音频回调函数
let audioCallback: any = null;
// 请求回调函数
let requestCallback: any = null;

//初始化解码器
const initDecoder = (fileSize: number, chunkSize: number) => {
  console.log(6666666, Module, fileSize, chunkSize);
  console.log(Module.asm.N);

  // 调用WebAssembly模块的初始化函数 日志级别为1
  var ret = Module._initDecoder(fileSize, 1);

  // 初始化成功，分配内存
  if (0 == ret) {
    cacheBuffer = Module._malloc(chunkSize);
  }
  // 向主线程发送初始化响应
  var objData = {
    t: 0,
    e: ret,
  };
  self.postMessage(objData);
};

//反初始化
const uninitDecoder = () => {
  // 调用WebAssembly模块的反初始化函数
  var ret = Module._uninitDecoder();
  // 记录反初始化返回值
  // 释放缓存的内存
  if (cacheBuffer != null) {
    Module._free(cacheBuffer);
    cacheBuffer = null;
  }
};

//打开解码器
const openDecoder = () => {
  console.log("open", 88888888);

  // 准备调用参数
  var paramCount = 7,
    paramSize = 4;
  var paramByteBuffer = Module._malloc(paramCount * paramSize);
  var ret = Module._openDecoder(
    paramByteBuffer,
    paramCount,
    videoCallback,
    audioCallback,
    requestCallback
  );

  // 解码器打开成功，处理解码器信息
  if (ret == 0) {
    // 提取解码器参数
    var paramIntBuff = paramByteBuffer >> 2;
    var paramArray = Module.HEAP32.subarray(
      paramIntBuff,
      paramIntBuff + paramCount
    );
    var duration = paramArray[0];
    var videoPixFmt = paramArray[1];
    var videoWidth = paramArray[2];
    var videoHeight = paramArray[3];
    var audioSampleFmt = paramArray[4];
    var audioChannels = paramArray[5];
    var audioSampleRate = paramArray[6];

    // 向主线程发送解码器信息
    var objData = {
      t: 2,
      e: ret,
      v: {
        d: duration,
        p: videoPixFmt,
        w: videoWidth,
        h: videoHeight,
      },
      a: {
        f: audioSampleFmt,
        c: audioChannels,
        r: audioSampleRate,
      },
    };
    self.postMessage(objData);
  } else {
    // 解码器打开失败，向主线程发送错误信息
    let objData: any = {
      t: 2,
      e: ret,
    };
    self.postMessage(objData);
  }
  // 释放参数内存
  Module._free(paramByteBuffer);
};

//关闭解码器
const closeDecoder = () => {
  // 停止解码定时器
  if (decodeTimer) {
    clearInterval(decodeTimer);
    decodeTimer = null;
  }

  // 调用WebAssembly模块的关闭解码器函数
  Module._closeDecoder();

  // 向主线程发送关闭解码器响应
  var objData = {
    t: 3,
    e: 0,
  };
  self.postMessage(objData);
};

//开始解码
const startDecoding = (interval: number) => {
  // 停止当前的解码定时器并设置新的解码间隔
  if (decodeTimer) {
    clearInterval(decodeTimer);
  }
  decodeTimer = setInterval(decode, interval);
};

//解码方法
const decode = () => {
  var ret = Module._decodeOnePacket();
  // 解码完成
  if (ret == 7) {
    self.decoder.pauseDecoding();
    var objData = {
      t: 8,
    };
    self.postMessage(objData);
  }

  // 处理旧帧
  while (ret == 9) {
    ret = Module._decodeOnePacket();
  }
};

//暂停解码
const pauseDecoding = () => {
  // 若存在解码定时器则停止
  if (decodeTimer) {
    clearInterval(decodeTimer);
    decodeTimer = null;
  }
};

//发送给解码器
const sendData = (data: ArrayBuffer) => {
  var typedArray = new Uint8Array(data);
  Module.HEAPU8.set(typedArray, cacheBuffer);
  Module._sendData(cacheBuffer, typedArray.length);
};

//跳转
const seekTo = (ms: number) => {
  var ret = Module._seekTo(ms, accurateSeek ? 1 : 0);
  var objData = {
    t: 10,
    r: ret,
  };
  self.postMessage(objData);
};

const processReq = (req: Req) => {
  console.log(req);

  switch (req.t) {
    case 0:
      initDecoder(req.s, req.c);
      break;
    case 1:
      uninitDecoder();
      break;
    case 2:
      openDecoder();
      break;
    case 3:
      closeDecoder();
      break;
    case 5:
      startDecoding(req.i);
      break;
    case 6:
      pauseDecoding();
      break;
    case 4:
      sendData(req.d);
      break;
    case 7:
      seekTo(req.ms);
      break;
    default:
  }
};

// 缓存数据
const cacheReq = (req) => {
  // 若请求存在则加入队列
  if (req) {
    tmpReqQue.push(req);
  }
};

const onWasmLoaded = () => {
  // 记录Wasm加载完成
  wasmLoaded = true;

  // 设置各种回调函数
  videoCallback = Module.addFunction(function (buff, size, timestamp) {
    var outArray = Module.HEAPU8.subarray(buff, buff + size);
    var data = new Uint8Array(outArray);
    var objData = {
      t: 4,
      s: timestamp,
      d: data,
    };
    self.postMessage(objData);
  }, "viid");

  audioCallback = Module.addFunction(function (buff, size, timestamp) {
    var outArray = Module.HEAPU8.subarray(buff, buff + size);
    var data = new Uint8Array(outArray);
    var objData = {
      t: 5,
      s: timestamp,
      d: data,
    };
    self.postMessage(objData);
  }, "viid");

  requestCallback = Module.addFunction(function (offset, availble) {
    var objData = {
      t: 9,
      o: offset,
      a: availble,
    };
    self.postMessage(objData);
  }, "vii");

  // 处理之前缓存的请求
  while (tmpReqQue.length > 0) {
    var req = tmpReqQue.shift();
    processReq(req);
  }
};

// 处理主线程发送过来的消息
self.onmessage = function (evt) {
  let req = evt.data;

  // 若WebAssembly未加载完成，则缓存请求
  if (!wasmLoaded) {
    cacheReq(req);
    return;
  }

  // 处理请求
  processReq(req);
};

// 当Wasm加载完成后调用的函数
function onLoad() {
  onWasmLoaded();
}
